//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "uart_bsp.h"
#include <stdio.h>
#include <string.h>

/*串口总管理结构体*/
typedef struct
{
    WHT_UART_enum Name;     //串口号
    WHT_UART_Info_t Info;   //提供给外部
    WHT_UART_Cache_t* Cache;//外设缓存,由外部提供

    FunctionalState Dma_Receive;        //串口DMA功能
    WHT_DMA_Config_t DMA_Send_Config;   //DMA配置
    WHT_DMA_Config_t DMA_Receive_Config;//DMA配置
}WHT_Data_t;


static WHT_Data_t WHT_UART1;
static WHT_Data_t WHT_UART2;
static WHT_Data_t WHT_UART3;
static WHT_Data_t WHT_UART4;
static WHT_Data_t WHT_UART5;
static WHT_Data_t WHT_UART6;
static WHT_Data_t WHT_UART7;
static WHT_Data_t WHT_UART8;
static WHT_Data_t WHT_UART9;
static WHT_Data_t WHT_UART10;

#define WHT_UART     ((WHT_Data_t*)cache->Private_Data)//简化操作


/*串口GPIO初始化*/
static void WHT_UART_BSP_GPIO_Init(const WHT_UART_Config_t *config)
{
    switch (config->Name)
    {
    case UART_1:
        WHT_GPIO_BSP.WHT_Set_Clock(PortA, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortA, Pin9 | Pin10, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortA, Pin9 | Pin10, Mode_AF_PP);
		WHT_GPIO_BSP.WHT_Set_AFIO(PortA, Pin9, AFIO_USART1);
		WHT_GPIO_BSP.WHT_Set_AFIO(PortA, Pin10, AFIO_USART1);
        break;
    case UART_2:
        WHT_GPIO_BSP.WHT_Set_Clock(PortA, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortA, Pin2 | Pin3, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortA, Pin2 | Pin3, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortA, Pin2, AFIO_USART2);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortA, Pin3, AFIO_USART2);
        break;
    case UART_3:
        WHT_GPIO_BSP.WHT_Set_Clock(PortB, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortB, Pin10 | Pin11, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortB, Pin10 | Pin11, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortB, Pin10, AFIO_USART3);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortB, Pin11, AFIO_USART3);
        break;
    case UART_4:
        WHT_GPIO_BSP.WHT_Set_Clock(PortC, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortC, Pin10 | Pin11, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortC, Pin10 | Pin11, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortC, Pin10, AFIO_UART4);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortC, Pin11, AFIO_UART4);
        break;
    case UART_5:
        WHT_GPIO_BSP.WHT_Set_Clock(PortC, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Clock(PortD, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortC, Pin12, Hig);
        WHT_GPIO_BSP.WHT_Set_Pin(PortD, Pin2, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortC, Pin12, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_Mode(PortD, Pin2, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortC, Pin12, AFIO_UART5);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortD, Pin2, AFIO_UART5);
        break;
    case UART_6:
        WHT_GPIO_BSP.WHT_Set_Clock(PortC, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortC, Pin6 | Pin7, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortC, Pin6 | Pin7, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortC, Pin6, AFIO_USART6);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortC, Pin7, AFIO_USART6);
        break;
    case UART_7:
        WHT_GPIO_BSP.WHT_Set_Clock(PortF, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortF, Pin6 | Pin7, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortF, Pin6 | Pin7, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortF, Pin6, AFIO_UART7);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortF, Pin7, AFIO_UART7);
        break;
    case UART_8:
        WHT_GPIO_BSP.WHT_Set_Clock(PortE, ENABLE);
        WHT_GPIO_BSP.WHT_Set_Pin(PortE, Pin0 | Pin1, Hig);
        WHT_GPIO_BSP.WHT_Set_Mode(PortE, Pin0 | Pin1, Mode_AF_PP);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortE, Pin0, AFIO_UART8);
        WHT_GPIO_BSP.WHT_Set_AFIO(PortE, Pin1, AFIO_UART8);
        break;
    default:
        break;
    }
}
/*串口中断优先级配置*/
static void WHT_UART_BSP_NVIC_Configuration(const WHT_UART_Config_t *config)
{
    IRQn_Type IRQn;

    /* 配置中断源 */
    switch (config->Name)
    {
#if defined(STM32F40_41xxx) || defined(STM32F446xx)
    case UART_1:IRQn = USART1_IRQn; break;
    case UART_2:IRQn = USART2_IRQn; break;
    case UART_3:IRQn = USART3_IRQn; break;
    case UART_4:IRQn = UART4_IRQn;  break;
    case UART_5:IRQn = UART5_IRQn;  break;
    case UART_6:IRQn = USART6_IRQn; break;
#endif /* STM32F40_41xxx || STM32F446xx */

#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F469_479xx)
    case UART_1:IRQn = USART1_IRQn; break;
    case UART_2:IRQn = USART2_IRQn; break;
    case UART_3:IRQn = USART3_IRQn; break;
    case UART_4:IRQn = UART4_IRQn;  break;
    case UART_5:IRQn = UART5_IRQn;  break;
    case UART_6:IRQn = USART6_IRQn; break;
    case UART_7:IRQn = UART7_IRQn;  break;
    case UART_8:IRQn = UART8_IRQn;  break;
#endif /* STM32F427_437xx || STM32F429_439xx || STM32F469_479xx */

#if defined(STM32F410xx) || defined(STM32F401xx) || defined(STM32F411xE)
    case UART_1:IRQn = USART1_IRQn; break;
    case UART_2:IRQn = USART2_IRQn; break;
    case UART_6:IRQn = USART6_IRQn; break;    
#endif /* STM32F410xx || STM32F401xx || STM32F411xE */

#if defined(STM32F412xG)
    case UART_1:IRQn = USART1_IRQn; break;
    case UART_2:IRQn = USART2_IRQn; break;
    case UART_3:IRQn = USART3_IRQn; break;
    case UART_6:IRQn = USART6_IRQn; break;                       
#endif /* STM32F412xG */

#if defined(STM32F413_423xx)
    case UART_1:IRQn = USART1_IRQn; break;
    case UART_2:IRQn = USART2_IRQn; break;
    case UART_3:IRQn = USART3_IRQn; break;
    case UART_4:IRQn = UART4_IRQn;  break;
    case UART_5:IRQn = UART5_IRQn;  break;
    case UART_6:IRQn = USART6_IRQn; break;
    case UART_7:IRQn = UART7_IRQn;  break;
    case UART_8:IRQn = UART8_IRQn;  break;
    case UART_9:IRQn = UART9_IRQn;  break;
    case UART_10:IRQn = UART10_IRQn;break;
#endif /* STM32F413_423xx */
    default:
        return;
    }

    NVIC_SetPriority(IRQn, config->PreemptionPriority);
    NVIC_EnableIRQ(IRQn);
}
/*串口注册*/
static ErrorStatus WHT_UART_BSP_Register(const WHT_UART_Config_t* config, const WHT_UART_Cache_t* cache)
{
    if ((WHT_UART != NULL) && (cache->Info != NULL))
        return SUCCESS;
    
    switch (config->Name)
    {
    case UART_1:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART1; break;
    case UART_2:RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART2; break;
    case UART_3:RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART3; break;
    case UART_4:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);  ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART4; break;
    case UART_5:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);  ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART5; break;
    case UART_6:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART6; break;
    case UART_7:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART7, ENABLE);  ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART7; break;
    case UART_8:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART8, ENABLE);  ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART8; break;
    //case UART_9:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART9, ENABLE);  ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART9; break;
    //case UART_10:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART10, ENABLE);  ((WHT_UART_Cache_t*)cache)->Private_Data = &WHT_UART10; break;
    default: return ERROR;
    }

    WHT_UART->Name = config->Name;
    ((WHT_UART_Cache_t*)cache)->Info = &WHT_UART->Info;
    WHT_UART->DMA_Send_Config.IT_Callback = NULL;
    WHT_UART->DMA_Receive_Config.IT_Callback = NULL;

    /*串口中断优先级配置*/
    WHT_UART_BSP_NVIC_Configuration(config);

    //将串口注册到DMA上
    switch (config->Name)
    {
    case UART_1:
        WHT_UART->DMA_Send_Config.Stream = Stream_USART1_TX;
        WHT_UART->DMA_Send_Config.Channel = Channel_USART1_TX;
        WHT_UART->DMA_Receive_Config.Stream = Stream_USART1_RX_1;
        WHT_UART->DMA_Receive_Config.Channel = Channel_USART1_RX_1;
        break;
    case UART_2:
        WHT_UART->DMA_Send_Config.Stream = Stream_USART2_TX;
        WHT_UART->DMA_Send_Config.Channel = Channel_USART2_TX;
        WHT_UART->DMA_Receive_Config.Stream = Stream_USART2_RX;
        WHT_UART->DMA_Receive_Config.Channel = Channel_USART2_RX;
        break;
    case UART_3:
        WHT_UART->DMA_Send_Config.Stream = Stream_USART3_TX_1;
        WHT_UART->DMA_Send_Config.Channel = Channel_USART3_TX_1;
        WHT_UART->DMA_Receive_Config.Stream = Stream_USART3_RX;
        WHT_UART->DMA_Receive_Config.Channel = Channel_USART3_RX;
        break;
    case UART_4:
        WHT_UART->DMA_Send_Config.Stream = Stream_UART4_TX;
        WHT_UART->DMA_Send_Config.Channel = Channel_UART4_TX;
        WHT_UART->DMA_Receive_Config.Stream = Stream_UART4_RX;
        WHT_UART->DMA_Receive_Config.Channel = Channel_UART4_RX;
        break;
    case UART_5:
        WHT_UART->DMA_Send_Config.Stream = Stream_UART5_TX;
        WHT_UART->DMA_Send_Config.Channel = Channel_UART5_TX;
        WHT_UART->DMA_Receive_Config.Stream = Stream_UART5_RX;
        WHT_UART->DMA_Receive_Config.Channel = Channel_UART5_RX;
        break;
    case UART_6:
        WHT_UART->DMA_Send_Config.Stream = Stream_USART6_TX_1;
        WHT_UART->DMA_Send_Config.Channel = Channel_USART6_TX_1;
        WHT_UART->DMA_Receive_Config.Stream = Stream_USART6_RX_1;
        WHT_UART->DMA_Receive_Config.Channel = Channel_USART6_RX_1;
        break;
    case UART_7:
        WHT_UART->DMA_Send_Config.Stream = Stream_UART7_TX;
        WHT_UART->DMA_Send_Config.Channel = Channel_UART7_TX;
        WHT_UART->DMA_Receive_Config.Stream = Stream_UART7_RX;
        WHT_UART->DMA_Receive_Config.Channel = Channel_UART7_RX;
        break;
    case UART_8:
        WHT_UART->DMA_Send_Config.Stream = Stream_UART8_TX;
        WHT_UART->DMA_Send_Config.Channel = Channel_UART8_TX;
        WHT_UART->DMA_Receive_Config.Stream = Stream_UART8_RX;
        WHT_UART->DMA_Receive_Config.Channel = Channel_UART8_RX;
        break;
    }
    WHT_DMA_BSP.WHT_Register(&WHT_UART->DMA_Send_Config);
    WHT_DMA_BSP.WHT_Register(&WHT_UART->DMA_Receive_Config);
    return SUCCESS;
}
/*串口配置*/
static void WHT_UART_BSP_Config(const WHT_UART_Config_t* config, const WHT_UART_Cache_t* cache)
{
    USART_InitTypeDef USART_InitStruct;
    
    if ((WHT_UART == NULL) || (cache->Info == NULL))
        return;

    WHT_UART->Cache = (WHT_UART_Cache_t*)cache;

    /*临时关闭串口*/
    USART_Cmd((USART_TypeDef*)WHT_UART->Name, DISABLE);
    /*串口相关GPIO初始化*/
    WHT_UART_BSP_GPIO_Init(config);

    /*初始化配置串口相关寄存器*/
    USART_InitStruct.USART_BaudRate = config->Bps;                              //串口波特率
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;                    //数据长度    
    USART_InitStruct.USART_StopBits = config->StopBits << 12;                   //停止位个数
    USART_InitStruct.USART_Parity = config->Parity;                             //校验位个数
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件控制流
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;                //发送和接收
    USART_Init((USART_TypeDef*)WHT_UART->Name, &USART_InitStruct);

    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_RXNE, DISABLE);//关闭中断串口接收
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_IDLE, DISABLE);//关闭中断串口空闲
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TXE, DISABLE); //关闭发送寄存器为空进入中断
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TC, DISABLE);  //关闭数据发送完成且发送寄存器为空进入中断

    /*使能串口*/
    USART_Cmd((USART_TypeDef*)WHT_UART->Name, ENABLE);
}


/*串口阻塞发送*/
static void WHT_UART_BSP_Send(const WHT_UART_Cache_t* cache)
{
    WHT_UART->Info.Tx_State = UART_Tx_Busy;
    USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Tx, DISABLE);//关闭串口发送DMA请求
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TXE, DISABLE);
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TC, DISABLE);
    USART_ClearFlag((USART_TypeDef*)WHT_UART->Name, USART_FLAG_TC);        //清除上次发送完成状态
    for (unsigned int tx_count = 0; tx_count < WHT_UART->Cache->Tx_Count; tx_count++)
    {
        USART_SendData((USART_TypeDef*)WHT_UART->Name, WHT_UART->Cache->Tx_Buf[tx_count]);
        while (!USART_GetFlagStatus((USART_TypeDef*)WHT_UART->Name, USART_FLAG_TXE));//等待发送寄存器为空
    }
    while (!USART_GetFlagStatus((USART_TypeDef*)WHT_UART->Name, USART_FLAG_TC));     //等待发送完成且发送寄存器为空
    WHT_UART->Info.Tx_State = UART_Tx_Idle;
}
/*串口中断发送*/
static void WHT_UART_BSP_Interrupt_Send(const WHT_UART_Cache_t* cache)
{
    WHT_UART->Info.Tx_State = UART_Tx_Busy;
    USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Tx, DISABLE);//关闭串口发送DMA请求
    /*默认寄存器TC=1,TXE=1*/
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TXE, ENABLE);  //使能发送寄存器为空进入中断
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TC, ENABLE);   //使能数据发送完成且发送寄存器为空进入中断
}
/*串口DMA发送*/
static void WHT_UART_BSP_DMA_Send(const WHT_UART_Cache_t* cache)
{
    DMA_InitTypeDef DMA_InitStruct =
    {
        .DMA_Channel            = 0,                          //DMA通道
        .DMA_PeripheralBaseAddr = 0,                          //外设基地址
        .DMA_Memory0BaseAddr    = 0,                          //存储器地址
        .DMA_DIR                = DMA_DIR_MemoryToPeripheral, //M->P
        .DMA_BufferSize         = 0,                          //传输个数
        .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,  //外设地址不递增
        .DMA_MemoryInc          = DMA_MemoryInc_Enable,       //存储器地址递增
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,//外设数据大小为字节
        .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,    //存储器数据大小为字节，跟外设数据大小相同
        .DMA_Mode               = DMA_Mode_Normal,            //单次传输模式
        .DMA_Priority           = DMA_Priority_Low,           //优先级最低
        .DMA_FIFOMode           = DMA_FIFOMode_Disable,       //FIFO模式
        .DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull,//FIFO阈值
        .DMA_MemoryBurst        = DMA_MemoryBurst_Single,     //内存突发传输
        .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single, //外设突发传输
    };

    switch (WHT_UART->Name)
    {
    case UART_1:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART1->DR;break;//外设基地址
    case UART_2:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART2->DR;break;
    case UART_3:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART3->DR;break;
    case UART_4:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART4->DR; break;
    case UART_5:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART5->DR; break;
    case UART_6:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART6->DR;break;
    case UART_7:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART7->DR; break;
    case UART_8:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART8->DR; break;
    default:
        return;
    }
    DMA_InitStruct.DMA_Channel = WHT_UART->DMA_Send_Config.Channel;            //DMA通道
    DMA_InitStruct.DMA_Memory0BaseAddr = (unsigned int)WHT_UART->Cache->Tx_Buf;//存储器地址
    DMA_InitStruct.DMA_BufferSize = WHT_UART->Cache->Tx_Count;                 //传输数据个数
    WHT_UART->DMA_Send_Config.DMA_InitStruct = &DMA_InitStruct;

    WHT_UART->Info.Tx_State = UART_Tx_Busy;//发送置为忙碌;
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TXE, DISABLE);//发送寄存器为空
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TC, DISABLE); //数据发送完成且发送寄存器为空

    while (WHT_UART->DMA_Send_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
    WHT_UART->DMA_Send_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
    WHT_DMA_BSP.WHT_Config(&WHT_UART->DMA_Send_Config);      //配置当前DMA

    USART_ClearFlag((USART_TypeDef*)WHT_UART->Name, USART_FLAG_TC);
    USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Tx, ENABLE);//使能串口DMA发送请求
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TC, ENABLE);  //数据发送完成且发送寄存器为空
}

/*串口中断接收*/
static void WHT_UART_BSP_Interrupt_Receive(const WHT_UART_Cache_t* cache)
{
    USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Rx, DISABLE);//关闭串口DMA接收请求

    WHT_UART->Info.Rx_State = UART_Rx_Idle;
    WHT_UART->Cache->Rx_Count = 0;
    WHT_UART->Dma_Receive = DISABLE;

    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_RXNE, ENABLE);//接收寄存器非空
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_IDLE, ENABLE);//数据接收完成且总线空闲
    ((USART_TypeDef*)WHT_UART->Name)->CR1 |= USART_Mode_Rx;               //开启串口接收
}
/*串口DMA接收*/
static void WHT_UART_BSP_DMA_Receive(const WHT_UART_Cache_t* cache)
{
    DMA_InitTypeDef DMA_InitStruct =
    {
        .DMA_Channel            = 0,                          //DMA通道
        .DMA_PeripheralBaseAddr = 0,                          //外设基地址
        .DMA_Memory0BaseAddr    = 0,                          //存储器地址
        .DMA_DIR                = DMA_DIR_PeripheralToMemory, //P->M
        .DMA_BufferSize         = 0,                          //传输个数
        .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,  //外设地址不递增
        .DMA_MemoryInc          = DMA_MemoryInc_Enable,       //存储器地址递增
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,//外设数据大小为字节
        .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,    //存储器数据大小为字节，跟外设数据大小相同
        .DMA_Mode               = DMA_Mode_Normal,            //单次传输模式
        .DMA_Priority           = DMA_Priority_Low,           //优先级最低
        .DMA_FIFOMode           = DMA_FIFOMode_Disable,       //FIFO模式
        .DMA_FIFOThreshold      = DMA_FIFOThreshold_Full,     //FIFO阈值
        .DMA_MemoryBurst        = DMA_MemoryBurst_Single,     //内存突发传输
        .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single, //外设突发传输
    };

    switch (WHT_UART->Name)
    {
    case UART_1:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART1->DR;break;//外设基地址
    case UART_2:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART2->DR;break;
    case UART_3:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART3->DR;break;
    case UART_4:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART4->DR; break;
    case UART_5:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART5->DR; break;
    case UART_6:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&USART6->DR;break;
    case UART_7:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART7->DR; break;
    case UART_8:DMA_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&UART8->DR; break;
    default:
        return;
    }
    DMA_InitStruct.DMA_Channel = WHT_UART->DMA_Receive_Config.Channel;         //DMA通道
    DMA_InitStruct.DMA_Memory0BaseAddr = (unsigned int)WHT_UART->Cache->Rx_Buf;//存储器地址
    DMA_InitStruct.DMA_BufferSize = WHT_UART->Cache->Rx_Buf_Size;              //传输数据个数
    WHT_UART->DMA_Receive_Config.DMA_InitStruct = &DMA_InitStruct;

    WHT_UART->Info.Rx_State = UART_Rx_Idle;
    WHT_UART->Dma_Receive = ENABLE;
    WHT_UART->Cache->Rx_Count = 0;

    while (WHT_UART->DMA_Receive_Config.Info->BSP_Mutex == SET);//没有外设使用此通道的DMA
    WHT_UART->DMA_Receive_Config.Info->BSP_Mutex = SET;         //开启互斥锁
    WHT_DMA_BSP.WHT_Config(&WHT_UART->DMA_Receive_Config);      //配置当前DMA

    USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Rx, ENABLE); //使能串口DMA接收请求
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_RXNE, DISABLE);//接收寄存器非空
    USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_IDLE, ENABLE); //数据接收完成且总线空闲
    ((USART_TypeDef*)WHT_UART->Name)->CR1 |= USART_Mode_Rx;                //开启串口接收
}

/*全局常量*/
const WHT_UART_BSP_t WHT_UART_BSP =
{
    .WHT_Register          = WHT_UART_BSP_Register,
    .WHT_Config            = WHT_UART_BSP_Config,
    .WHT_Send              = WHT_UART_BSP_Send,
    .WHT_Interrupt_Send    = WHT_UART_BSP_Interrupt_Send,
    .WHT_DMA_Send          = WHT_UART_BSP_DMA_Send,
    .WHT_DMA_Receive       = WHT_UART_BSP_DMA_Receive,
    .WHT_Interrupt_Receive = WHT_UART_BSP_Interrupt_Receive,
};





/*串口中断发送回调函数*/
static void WHT_UART_BSP_IRQHandler_Send(const WHT_UART_Cache_t* cache, unsigned int* tx_count)
{
    if (USART_GetITStatus((USART_TypeDef*)WHT_UART->Name, USART_IT_TXE) == SET)//发送寄存器为空
    {
        if (*tx_count >= WHT_UART->Cache->Tx_Count)//是否数据发送完
        {
            USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TXE, DISABLE);
            *tx_count = 0;
        }
        else
        {
            USART_SendData((USART_TypeDef*)WHT_UART->Name, WHT_UART->Cache->Tx_Buf[(*tx_count)++]);
        }
    }
    else if (USART_GetITStatus((USART_TypeDef*)WHT_UART->Name, USART_IT_TC) == SET)//发送完成且发送寄存器为空
    {
        USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_TC, DISABLE);  //DMA发送有使用此串口中断，小心DMA未及时处理导致此中断发生
        USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Tx, DISABLE);//关闭DMA请求
        WHT_UART->Info.Tx_State = UART_Tx_Idle;
        if (WHT_UART->Cache->Tx_Idle_IT_Callback != NULL)
            WHT_UART->Cache->Tx_Idle_IT_Callback();
    }
}
/*串口中断接收回调函数*/
static void WHT_UART_BSP_IRQHandler_Receive(const WHT_UART_Cache_t* cache)
{
    if (WHT_UART->Dma_Receive == DISABLE)
    {
        if (USART_GetITStatus((USART_TypeDef*)WHT_UART->Name, USART_IT_RXNE) == SET)//接收寄存器非空
        {
            if (WHT_UART->Cache->Rx_Count >= WHT_UART->Cache->Rx_Buf_Size)//接收数据个数是否超标
                USART_ReceiveData((USART_TypeDef*)WHT_UART->Name);        //丢弃接收到的数据
            else
            {
                WHT_UART->Cache->Rx_Buf[WHT_UART->Cache->Rx_Count] = USART_ReceiveData((USART_TypeDef*)WHT_UART->Name);
                WHT_UART->Cache->Rx_Count++;
                WHT_UART->Info.Rx_State = UART_Rx_Busy;
            }
        }
        else if (USART_GetITStatus((USART_TypeDef*)WHT_UART->Name, USART_IT_IDLE) == SET)//接收空闲
        {
            ((USART_TypeDef*)WHT_UART->Name)->CR1 &= ~USART_Mode_Rx; //关闭串口接收
            USART_ReceiveData((USART_TypeDef*)WHT_UART->Name);       //读取一下接收寄存器数据清除空闲标志位
            WHT_UART->Info.Rx_State = WHT_UART->Cache->Rx_Count >= WHT_UART->Cache->Rx_Buf_Size ? UART_Rx_Overflow : UART_Rx_Idle;//接收数据个数是否超标
            if (WHT_UART->Cache->Rx_Idle_IT_Callback != NULL)
                WHT_UART->Cache->Rx_Idle_IT_Callback();
        }
    }
    else
    {
        if (USART_GetITStatus((USART_TypeDef*)WHT_UART->Name, USART_IT_IDLE) == SET)//接收空闲
        {
            ((USART_TypeDef*)WHT_UART->Name)->CR1 &= ~USART_Mode_Rx;               //关闭串口接收
            USART_DMACmd((USART_TypeDef*)WHT_UART->Name, USART_DMAReq_Rx, DISABLE);//关闭串口DMA接收请求
            WHT_UART->Cache->Rx_Count = WHT_UART->Cache->Rx_Buf_Size - WHT_DMA_BSP.WHT_Get_Curr_Data_Count(&WHT_UART->DMA_Receive_Config);
            WHT_DMA_BSP.WHT_Close(&WHT_UART->DMA_Receive_Config);                  //手动关闭DMA通道
            USART_ITConfig((USART_TypeDef*)WHT_UART->Name, USART_IT_IDLE, DISABLE);//数据接收完成且总线空闲
            USART_ReceiveData((USART_TypeDef*)WHT_UART->Name);                     //在读取一次接收到的数据,用来清除空闲标志位
            WHT_UART->Info.Rx_State = UART_Rx_Idle;
            if (WHT_UART->Cache->Rx_Idle_IT_Callback != NULL)
                WHT_UART->Cache->Rx_Idle_IT_Callback();
        }
    }
}

/*串口1中断服务程序*/
void USART1_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART1.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART1.Cache);
}
/*串口2中断服务程序*/
void USART2_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART2.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART2.Cache);
}
/*串口3中断服务程序*/
void USART3_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART3.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART3.Cache);
}
/*串口4中断服务程序*/
void UART4_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART4.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART4.Cache);
}
/*串口5中断服务程序*/
void UART5_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART5.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART5.Cache);
}
/*串口6中断服务程序*/
void USART6_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART6.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART6.Cache);
}
/*串口7中断服务程序*/
void UART7_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART7.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART7.Cache);
}
/*串口8中断服务程序*/
void UART8_IRQHandler(void)
{
    static unsigned int tx_count = 0;

    WHT_UART_BSP_IRQHandler_Send(WHT_UART8.Cache, &tx_count);
    WHT_UART_BSP_IRQHandler_Receive(WHT_UART8.Cache);
}
